﻿using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using NiuPi.Database.Platform;
using SqlSugar;
using Furion.FriendlyException;
using Furion;
using NiuPi.Tools;
using Microsoft.AspNetCore.Authorization;
using Furion.DataEncryption;
using Newtonsoft.Json;
using NiuPi.Platform.Const;
using NiuPi.Platform.Entity;

namespace NiuPi.Platform.Services
{
    /// <summary>
    /// 用户管理/授权模块
    /// </summary>
    [Route("api/platform/[controller]")]
    [ApiDescriptionSettings("platform")]
    public class UserService : IDynamicApiController, ITransient
    {
        private readonly ILogger<UserService> Logger;
        private readonly IHttpContextAccessor HttpContextAccessor;
        private readonly SqlSugarScope Db;
        public UserService(ILogger<UserService> _Logger, IHttpContextAccessor _HttpContextAccessor, SqlSugarScope _Db)
        {
            Logger = _Logger;
            HttpContextAccessor = _HttpContextAccessor;
            Db = _Db;
        }
        /// <summary>
        /// 根据角色ID获取权限数据
        /// </summary>
        /// <param name="RoleId"></param>
        /// <returns></returns>
        public async Task<string[]> GetPermissionsByRoleID(int RoleId)
        {
            var permissions = new List<string>();
            var result = await Db.Queryable<RolePermission>().Where(x => x.RoleId == RoleId).ToListAsync();
            if (result.Count > 0)
            {

                foreach (var item in result)
                {
                    permissions.Add(item.Permission);
                }
            }
            return permissions.ToArray();
        }
        /// <summary>
        /// 账号密码登录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> Login(User input)
        {
            // 获取加密后的密码
            var encryptPasswod = MD5Encryption.Encrypt(input.Password);
            // 判断用户名和密码是否正确
            var user = await Db.Queryable<User>().Where(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod) && u.Status == 0).FirstAsync();
            _ = user ?? throw Oops.Oh("账号密码错误/账号已被封禁！");
            // 生成Token令牌
            var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.CLAINM_USERID, user.Id},
                {ClaimConst.TENANT_ID, user.TenantId},
                {ClaimConst.CLAINM_ACCOUNT, user.Account},
                {ClaimConst.CLAINM_NAME, user.NickName},
                {ClaimConst.CLAINM_SUPERADMIN, user.AdminType}
            });
            // 设置Swagger自动登录
            HttpContextAccessor.HttpContext.SigninToSwagger(accessToken);
            // 生成刷新Token令牌
            var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, 43200);
            // 设置刷新Token令牌
            HttpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
            //根据用户的角色ID获取角色多个授权标识
            var permissions = await GetPermissionsByRoleID((int)user.RoleId);
            var userInfo = JsonConvert.SerializeObject(new UserInfo
            {
                Id = user.Id,
                TenantId=user.TenantId,
                Account = user.Account,
                NickName = user.NickName,
                Avatar = user.Avatar,
                Permissions = permissions,
                AccessToken = accessToken
            });
            return RestfulResult.Instance.OnSucceeded(JsonConvert.DeserializeObject<UserInfo>(userInfo));
        }
        /// <summary>
        /// 根据用户ID获取用户信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IActionResult> GetUserInfo(long id)
        {
            var user = await Db.Queryable<User>().Where(u => u.Id.Equals(id) && u.Status == 0).FirstAsync();
            _ = user ?? throw Oops.Oh("用户不存在/已被封禁！");
            var permissions = await GetPermissionsByRoleID((int)user.RoleId);
            var userInfo = JsonConvert.SerializeObject(new UserInfo
            {
                Id = user.Id,
                Account = user.Account,
                NickName = user.NickName,
                Avatar = user.Avatar,
                Permissions = permissions
            });
            return RestfulResult.Instance.OnSucceeded(JsonConvert.DeserializeObject<UserInfo>(userInfo));
        }
        /// <summary>
        /// 根据请求用户的AccessToken来退出登录
        /// 退出登录时需要修改lastLoginIP，lastLoginTime
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> SignOut(User input)
        {
            var accessToken = HttpContextAccessor.HttpContext.Request.Headers["access-token"].ToString();
            _ = accessToken ?? throw Oops.Oh("您没有权限进行此项操作！");
            var model = input.Adapt<User>();
            var user = await Db.Queryable<User>().Where(u => u.Id.Equals(model.Id) && u.Status == 0).FirstAsync();
            _ = user ?? throw Oops.Oh("用户不存在/已被封禁！");
            var row = await Db.Updateable<User>()
                .SetColumns(x => x.LastLoginIP == HttpContextAccessor.HttpContext.Request.HttpContext.GetRequestIPv4())
                .SetColumns(x => x.LastLoginTime == Time.GetTimeStamp())
                .Where(o => o.Id == user.Id).ExecuteCommandAsync();
            if (row <= 0)
            {
                throw Oops.Oh("退出失败，请重试！");
            }
            return RestfulResult.Instance.OnSucceeded();
        }
        /// <summary>
        /// 添加平台用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Add(User input)
        {
            //自动将前端参数映射到User模型
            var model = input.Adapt<User>();
            if (Db.Queryable<User>().AnyAsync(x => x.Account == input.Account).Result) throw Oops.Oh("账号已存在！");
            if (Db.Queryable<User>().AnyAsync(x => x.Phone == input.Phone).Result) throw Oops.Oh("手机号已绑定！");
            var result = await Db.Insertable(model).ExecuteCommandAsync();
            if (result > 0)
            {
                return RestfulResult.Instance.OnSucceeded();
            }
            else
            {
                return RestfulResult.Instance.OnFailed();
            }
        }
        /// <summary>
        /// 编辑平台用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>级
        [HttpPost]
        public async Task<IActionResult> Edit(User input)
        {
            //自动将前端参数映射到User模型
            var model = input.Adapt<User>();
            var result = await Db.Updateable(model).ExecuteCommandAsync();
            if (result > 0)
            {
                return RestfulResult.Instance.OnSucceeded();
            }
            else
            {
                return RestfulResult.Instance.OnFailed();
            }
        }
        /// <summary>
        /// 删除平台用户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Del(int id)
        {
            var result = await Db.Deleteable<User>(id).ExecuteCommandAsync();
            if (result > 0)
            {
                return RestfulResult.Instance.OnSucceeded();
            }
            else
            {
                return RestfulResult.Instance.OnFailed();
            }
        }
        /// <summary>
        /// 根据ID查询平台用户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IActionResult> GetOne(int id)
        {
            var user = await Db.Queryable<User>().Where(x => x.Id == id).FirstAsync();
            return RestfulResult.Instance.OnSucceeded(user);
        }

        /// <summary>
        /// 查询平台用户列表
        /// </summary>
        /// <param name="pageIndex">当前页</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns></returns>
        public async Task<IActionResult> GetList(int pageIndex = 0, int pageSize = 10)
        {
            RefAsync<int> totalCount = 0;
            var result = await Db.Queryable<User, Role>((u, r) => new JoinQueryInfos(JoinType.Left, u.RoleId == r.Id))
                .OrderBy(u => u.Id)
                .Select<User>().ToPageListAsync(pageIndex, pageSize, totalCount);
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
            foreach (var item in result)
            {
                item.Phone = MD5Encryption.Encrypt(item.Phone);
            }
            return RestfulResult.Instance.OnPageSucceeded(
                  new PageResult<User>
                  {
                      PageNo = pageIndex,
                      PageSize = pageSize,
                      Rows = result,
                      TotalRows = totalCount,
                      TotalPage = totalPages
                  },
              App.HttpContext.Request.Headers
              );
        }
        /// <summary>
        /// 根据ID修改stauts状态
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> ChangeStatus(User input)
        {
            var result = await Db.Updateable<User>().SetColumns(x => x.Status == input.Status).Where(o => o.Id == input.Id).ExecuteCommandAsync();
            if (result > 0)
            {
                return RestfulResult.Instance.OnSucceeded();
            }
            else
            {
                return RestfulResult.Instance.OnFailed();
            }
        }
        /// <summary>
        /// 设置用户角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> SetRole(User input)
        {
            var result = await Db.Updateable<User>().SetColumns(x => x.RoleId == input.RoleId).Where(o => o.Id == input.Id).ExecuteCommandAsync();
            if (result > 0)
            {
                return RestfulResult.Instance.OnSucceeded();
            }
            else
            {
                return RestfulResult.Instance.OnFailed();
            }
        }
        /// <summary>
        /// 设置用户关联租户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> BindTenant(User input)
        {
            var result = await Db.Updateable<User>().SetColumns(x => x.TenantId == input.TenantId).Where(o => o.Id == input.Id).ExecuteCommandAsync();
            if (result > 0)
            {
                return RestfulResult.Instance.OnSucceeded();
            }
            else
            {
                return RestfulResult.Instance.OnFailed();
            }
        }
    }
}
